/*
 * ResourceReservation.cpp
 *
 *  Created on: Nov 21, 2008
 *      Author: Ryan
 */

#include "ResourceReservation.h"

ResourceReservation::ResourceReservation()
{
}

ResourceReservation::~ResourceReservation()
{
}

void ResourceReservation::reserve( OOInterface::ConstUnitPtr builder, OOInterface::ConstCommandPtr command, ResourceMap resources  )
{
	int timerDuration = 10000;

	BuilderReservedResources pair( command, resources );


	for( ResourceMap::iterator resource = resources.begin(); resource != resources.end(); ++resource )
	{
		ResourceMap::iterator i = _reservedResources.find( (*resource).first );
		float current = 0.0f;

		if( i != _reservedResources.end() )
		{
			current = (*i).second + (*resource).second;
			_reservedResources.erase( i );
		}
		else
			current = (*resource).second;

		_reservedResources.insert( std::pair< const OOInterface::Resource, float>( (*resource).first, current) );
	}



	_resources.push_back( std::pair< OOInterface::ConstUnitPtr, BuilderReservedResources >( builder, pair) );
	_timers.push_back( std::pair< OOInterface::ConstUnitPtr, int > ( builder, timerDuration ) );
}

void ResourceReservation::updateTimers()
{
	std::list < Timers::iterator > remove;

	for( Timers::iterator timer = _timers.begin(); timer != _timers.end(); ++timer )
	{
		--((*timer).second);
		if( (*timer).second <= 0 )
		{
			//Release the builder and the resources back into the pool
			OOInterface::ConstUnitPtr builder = (*timer).first;
			releaseExpiredResources( builder );

			remove.push_front( timer );
		}
	}

	for( std::list<Timers::iterator>::iterator iters = remove.begin(); iters != remove.end(); ++iters )
		_timers.erase( (*iters) );
}

void ResourceReservation::releaseExpiredResources( OOInterface::ConstUnitPtr builder )
{
	if( !builder.get() )
		return;

	for( BuilderResourceList::iterator pair = _resources.begin(); pair != _resources.end(); ++pair )
	{
		if( (*pair).first.get() && (*pair).first->getID() == builder->getID() )
		{
			BuilderReservedResources& resources = (*pair).second;

			for( ResourceMap::iterator resource = resources.second.begin(); resource != resources.second.end(); ++resource )
			{
				ResourceMap::iterator release = _reservedResources.find( (*resource).first );

				if( release != _reservedResources.end() )
				{
					float current = (*release).second - (*resource).second;
					_reservedResources.erase( release );
					_reservedResources.insert( std::pair< const OOInterface::Resource, float>( (*resource).first, current ));
				}


			}

			_resources.erase( pair );
			break;
		}
	}
}

bool ResourceReservation::isBuilderReserved( OOInterface::ConstUnitPtr builder )
{
	if( !builder.get() )
		return false;

	for( Timers::iterator timer = _timers.begin(); timer != _timers.end(); ++timer )
	{
		if( (*timer).first.get() && (*timer).first->getID() == builder->getID() )
			return true;
	}

	return false;
}

